//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//

/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using System.Collections.Generic;
using System.Text;
using EffiProz.Core.DataTypes;

namespace EffiProz.Core
{

    /**
     * Defines and enumerates reserved and non-reserved SQL
     * keywords. <p>
     *
     * @author  Nitin Chauhan
     * @author  fredt@users
     * @since 1.7.2
     * @version 1.7.2
     */
    public class Token
    {

        public String tokenStringOrginal = "";
        private String _tokenString = "";

        public string tokenString
        {
            get
            {
                return _tokenString;
            }

            set
            {
                tokenStringOrginal = _tokenString = value;
            }
        }

        public int tokenType = Tokens.X_UNKNOWN_TOKEN;
        public SqlType dataType;
        public Object tokenValue;
        public String namePrefix;
        public String namePrePrefix;
        public String namePrePrePrefix;
        public String charsetSchema;
        public String charsetName;
        public String fullString;
        public int lobMultiplierType = Tokens.X_UNKNOWN_TOKEN;
        public bool isDelimiter;
        public bool isDelimitedIdentifier;
        public bool isDelimitedPrefix;
        public bool isDelimitedPrePrefix;
        public bool isDelimitedPrePrePrefix;
        public bool isUndelimitedIdentifier;
        public bool isReservedIdentifier;
        public bool isCoreReservedIdentifier;
        public bool isHostParameter;
        public bool isMalformed;

        //
        public int position;
        public ExpressionColumn columnExpression;

        public void reset()
        {

            tokenString = "";
            tokenType = Tokens.X_UNKNOWN_TOKEN;
            dataType = null;
            tokenValue = null;
            namePrefix = null;
            namePrePrefix = null;
            namePrePrePrefix = null;
            charsetSchema = null;
            charsetName = null;
            fullString = null;
            lobMultiplierType = Tokens.X_UNKNOWN_TOKEN;
            isDelimiter = false;
            isDelimitedIdentifier = false;
            isDelimitedPrefix = false;
            isDelimitedPrePrefix = false;
            isDelimitedPrePrePrefix = false;
            isUndelimitedIdentifier = false;
            isReservedIdentifier = false;
            isCoreReservedIdentifier = false;
            isHostParameter = false;
            isMalformed = false;
        }

        public Token duplicate()
        {

            Token token = new Token();

            token.tokenString = tokenString;
            token.tokenType = tokenType;
            token.dataType = dataType;
            token.tokenValue = tokenValue;
            token.namePrefix = namePrefix;
            token.namePrePrefix = namePrePrefix;
            token.namePrePrePrefix = namePrePrePrefix;
            token.charsetSchema = charsetSchema;
            token.charsetName = charsetName;
            token.fullString = fullString;
            token.lobMultiplierType = lobMultiplierType;
            token.isDelimiter = isDelimiter;
            token.isDelimitedIdentifier = isDelimitedIdentifier;
            token.isDelimitedPrefix = isDelimitedPrefix;
            token.isDelimitedPrePrefix = isDelimitedPrePrefix;
            token.isDelimitedPrePrePrefix = isDelimitedPrePrePrefix;
            token.isUndelimitedIdentifier = isUndelimitedIdentifier;
            token.isReservedIdentifier = isReservedIdentifier;
            token.isCoreReservedIdentifier = isCoreReservedIdentifier;
            token.isHostParameter = isHostParameter;
            token.isMalformed = isMalformed;

            return token;
        }

        public String getFullString()
        {
            return fullString;
        }

        public String getSQL()
        {

            if (namePrefix == null && isUndelimitedIdentifier)
            {
                return tokenString;
            }

            if (tokenType == Tokens.X_VALUE)
            {
                return dataType.convertToSQLString(tokenValue);
            }

            StringBuilder sb = new StringBuilder();

            if (tokenType == Tokens.ASTERISK)
            {
                if (columnExpression != null
                        && columnExpression.opType == OpTypes.MULTICOLUMN
                        && columnExpression.nodes.Length > 0)
                {
                    sb.Append(' ');

                    for (int i = 0; i < columnExpression.nodes.Length; i++)
                    {
                        Expression e = columnExpression.nodes[i];
                        ColumnSchema c = e.getColumn();
                        String name;

                        if (e.opType == OpTypes.COALESCE)
                        {
                            sb.Append(e.getColumnName());

                            continue;
                        }

                        if (e.getRangeVariable().tableAlias == null)
                        {
                            name = c.getName().getSchemaQualifiedStatementName();
                        }
                        else
                        {
                            RangeVariable range = e.getRangeVariable();

                            name = range.tableAlias.getStatementName() + '.'
                                   + c.getName().statementName;
                        }

                        if (i > 0)
                        {
                            sb.Append(',');
                        }

                        sb.Append(name);
                    }

                    sb.Append(' ');
                }
                else
                {
                    return tokenString;
                }

                return sb.ToString();
            }

            if (namePrePrefix != null)
            {
                if (isDelimitedPrePrefix)
                {
                    sb.Append('"');
                    sb.Append(namePrePrefix);
                    sb.Append('"');
                }
                else
                {
                    sb.Append(namePrePrefix);
                }

                sb.Append('.');
            }

            if (namePrefix != null)
            {
                if (isDelimitedPrefix)
                {
                    sb.Append('"');
                    sb.Append(namePrefix);
                    sb.Append('"');
                }
                else
                {
                    sb.Append(namePrefix);
                }

                sb.Append('.');
            }

            if (isDelimitedIdentifier)
            {
                sb.Append('"');
                sb.Append(tokenString);
                sb.Append('"');
            }
            else
            {
                sb.Append(tokenString);
            }

            return sb.ToString();
        }

        /*
            for (int i = 0; i < tokens.length; i++) {
                if (tokens[i].schemaObjectIdentifier instanceof Expression) {
                    ColumnSchema column =
                        ((Expression) tokens[i].schemaObjectIdentifier)
                            .getColumn();

                    tokens[i].schemaObjectIdentifier = column.getName();
                }
            }
        */
        public static String getSQL(Token[] statement)
        {

            bool wasDelimiter = true;
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < statement.Length; i++)
            {
                if (!statement[i].isDelimiter && !wasDelimiter)
                {
                    sb.Append(' ');
                }

                sb.Append(statement[i].getSQL());

                wasDelimiter = statement[i].isDelimiter;
            }

            return sb.ToString();
        }
    }
}
